/*
 * =====================================================================================
 *
 *       Filename:  menu.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  25.01.2010 16:48:01
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Michal Antonczak (uzyszkodnik), uzyszkodnik.priv@gmail.com
 *        Company:  
 *
 * =====================================================================================
 */

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>

#include <sys/types.h>
#include <dirent.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

#include "menu.h"
#include "map.h"
#include "moonlander.h"

#include <SDL/SDL_ttf.h>
#include <SDL/SDL.h>



using namespace std;

void Menu::sdlinit(){

	

	if(SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO)<0){
		printf("sdl init error: %s", SDL_GetError());	
		exit(1);
	}
	if(TTF_Init()<0){
		printf("ttf init: %s", TTF_GetError());
		exit(1);
	}
	
	SDL_WM_SetCaption("llc",NULL);

	
/*


	img_flags = IMG_INIT_JPG;

	if((IMG_INIT(flags)&flags)!=flags)
		sdlimgerror("SDL_IMG initialization");
		
*/
	atexit(SDL_Quit);
	if((screen = SDL_SetVideoMode(800,600, 32, SDL_DOUBLEBUF | SDL_HWSURFACE))== NULL)
		sdlerror("video initialization");	
	SDL_EnableKeyRepeat(1,300);



}

Menu::~Menu(){
	while(!map_infos.empty()){
		delete  map_infos.back();
		map_infos.pop_back();
	}
}


int Menu::dirscan(char *name){
	int n;
	int i=0;
	TTF_Font* font;
	struct dirent** dirnames;
	font = TTF_OpenFont("mapfont.ttf", 15);

	Short_map_info *info,*prev;


	n = scandir(name,&dirnames,filter,compar); 

	if(n>0){

		info = new Short_map_info(font, string(dirnames[i]->d_name));
		info->pos.x =(800-info->mini->w)/2;
		info->pos.y =(600-info->mini->h)/2;
		pos = info->pos.x;
		map_infos.push_back(info);
		prev = info;

		for(i=1;i<n;i++){

			info = new Short_map_info(font, string(dirnames[i]->d_name));
			info->pos.x = prev->pos.x+prev->mini->w+40;
			info->pos.y =(600-info->mini->h)/2;
			prev = info;
			map_infos.push_back(info);
		}

	}
	if(n==-1)
		perror("scandir: ");	
	TTF_CloseFont(font);

}


int map_dir_filter(const struct dirent* a){

if( (!strcmp("map.png",a->d_name)) || ( !strcmp("collision.png",a->d_name ) ) ||  (!strcmp("config",a->d_name)) )
	return 1;
else
	return 0;

}

int filter(const struct dirent* a){
	
	struct stat  statz;

	struct dirent** file_list;	
	
	int n;

	stat(a->d_name, &statz);	
	
	if(!S_ISDIR(statz.st_mode))
		return 0;

//	if(!strcmp("..", a->d_name))
//		return 0;

	if(scandir(a->d_name, &file_list,map_dir_filter,NULL)==3){
		free(file_list);
		return 1;
	}
	else{
		free(file_list);
		return 0;
	}
	
}


int compar(const struct dirent** a,const struct dirent** b){
	int i;
	int lena,lenb;	
	int iter;
 	int ret;
	lena=strlen( a[0]->d_name);
	lenb=strlen(b[0]->d_name);
	
	if(lena<lenb)
		iter=lena;
	else
		iter=lenb;

	for(i=0;i<iter;i++){
		ret=a[0]->d_name[i]-b[0]->d_name[i];
		if(ret!=0)
			return ret;
	}

	if (lena==lenb)
		return 0;

	if(a[0]->d_name[i]!=0)
		return 1;
	else
		return -1;
	
}
/* 
void Menu::frame(){

	int i;
	SDL_Surface* img;
	SDL_Rect pos, cut,middle;

	img = map_infos[chosen]->mini;	

	middle.x = (799-img->w)/2;
	middle.y = (600-img->h)/2;
	SDL_BlitSurface(bg,NULL,screen,NULL);
	SDL_BlitSurface(map_infos[chosen]->mini,NULL,screen,&middle);

	pos.x=middle.x+map_infos[chosen]->mini->w+20;

	//loop drawing right side from the map in focus
	for(i=chosen+1;pos.x<799 && i<map_infos.size() ;i++){

		if( ( map_infos[i]->mini->w + pos.x )<799 ){

			pos.y = (600-map_infos[i]->mini->h)/2;

			SDL_BlitSurface(map_infos[i]->mini,NULL, screen,&pos);
			
			pos.x += map_infos[i]->mini->w+20;

		} else {
			pos.y = (600-map_infos[i]->mini->h)/2;
			cut.x = 0 ;
			cut.y = 0 ;
			cut.h = map_infos[i]->mini->h;	
			cut.w = map_infos[i]->mini->w+pos.x-800;
			SDL_BlitSurface(map_infos[i]->mini,&cut, screen, &pos);
		}
	}

	// loop drawing left side from the map in focus
	
	pos.x = middle.x - 20;

	for(i=chosen-1;i>=0 ;i--){

		if( ( pos.x - map_infos[i]->mini->w ) > 0 ){

			pos.y = (600-map_infos[i]->mini->h)/2;

			SDL_BlitSurface(map_infos[i]->mini,NULL, screen,&pos);
			
			pos.x -= map_infos[i]->mini->w-20;

		} else if( abs(pos.x-map_infos[i]->mini->w) < map_infos[i]->mini->w  ){
			pos.y = (600-map_infos[i]->mini->h)/2;

			cut.y = 0 ;

			cut.h = map_infos[i]->mini->h;	
			cut.w = map_infos[i]->mini->w - abs(pos.x-map_infos[i]->mini->w);
			cut.x = map_infos[i]->mini->w-cut.w;

			pos.x = 0;

		//	cut.h = map_infos[i]->mini->h;	
			//cut.w = map_infos[i]->mini->w+pos.x-800;
			SDL_BlitSurface(map_infos[i]->mini,&cut, screen, &pos);
		} else 
			break;

	}
		
}

*/

//mayhem
//that code sux
void Menu::frame(){

	int i;
	SDL_Rect cut;
	SDL_Rect poss;
	const int accel = 20;
	double tmpspeed;
	int maxspeed;
	double tmpmove;
	int tmppos;

	tmpmove = ( (double) ( accel*timezor )/1000);
	pos=(800-map_infos[chosen]->mini->w)/2;
	tmppos = map_infos[chosen]->pos.x;	

	if(tmppos<pos)
		tmpspeed=(pos-tmppos);
	else  if(tmppos>pos)
		tmpspeed = (tmppos - pos);
	else
		tmpspeed = 0 ;

	// some beatifull day maybe we'll put a nice formula here
	
	tmpspeed/=10;

	maxspeed = (int) tmpspeed;


	if(tmppos!=pos && maxspeed==0)
		maxspeed = 1;	

	 if(pos > map_infos[chosen]->pos.x){

		if((map_infos[chosen]->pos.x+mov)>pos)
			mov=(((double)(pos-map_infos[chosen]->pos.x)*timezor ))/1000;
		else
			mov+=tmpmove;
		
		if(mov > maxspeed)
			mov = maxspeed;

		for(i=0;i<map_infos.size();i++)
			map_infos[i]->pos.x+=(int)mov;	

	 }
		

	 if(pos < map_infos[chosen]->pos.x){

		if( (map_infos[chosen]->pos.x - mov ) < pos)
			mov= ( (double)((map_infos[chosen]->pos.x-pos)*timezor))/1000;
		else
			mov+=tmpmove;
		
		if(mov > maxspeed)
			mov = maxspeed;

		for(i=0;i<map_infos.size();i++)
			map_infos[i]->pos.x-=(int)mov;

	 }
	

	if(pos == map_infos[chosen]->pos.x)
		mov = 0;

	SDL_BlitSurface(bg,NULL,screen,NULL);

	 for(i=0;i<map_infos.size();i++){
		if( ( map_infos[i]->pos.x + map_infos[i]->mini->w ) > 0 && map_infos[i]->pos.x < 800 ){
			if(map_infos[i]->pos.x<0){

				poss.y = map_infos[i]->pos.y;
				cut.y = 0 ;
				cut.h = map_infos[i]->mini->h;	
				cut.w = map_infos[i]->pos.x+map_infos[i]->mini->w ;
				cut.x = map_infos[i]->mini->w-cut.w;
				poss.x = 0;

				SDL_BlitSurface(map_infos[i]->mini,&cut, screen, &poss);

			 }else if(map_infos[i]->pos.x+map_infos[i]->mini->w>799){

				poss.y = map_infos[i]->pos.y;
				poss.x = map_infos[i]->pos.x;

				if(poss.x<0){
					cut.x=abs(poss.x);
					poss.x=0;
				} else
					cut.x=0;

				cut.y = 0 ;
				cut.h = map_infos[i]->mini->h;	
				cut.w = 800-cut.x;

				if(poss.x<0)
					poss.x = 0;

				SDL_BlitSurface(map_infos[i]->mini,&cut, screen, &poss);

			} else{
				
				SDL_BlitSurface(map_infos[i]->mini, NULL, screen, &map_infos[i]->pos);
			}


		}		
			
	}
		
}

void Menu::menuloop(){

	chosen  =0;	
	Moonlander* game;
	dirscan("./");
	Uint32 t;
	mov = 0;
	bg = SDL_CreateRGBSurface(SDL_HWSURFACE, 800,600,32,0,0,0,0);
	SDL_Event event;
	timezor = FRAME_TIME;

	char *ourprostring;
	ourprostring = new char[5000];
	while(1){	
		frame_timer.start();
		while(SDL_PollEvent(&event)){
			switch(event.type){
				case SDL_QUIT:
					exit(1);
					break;
				
				case SDL_KEYDOWN:
					switch(event.key.keysym.sym){
						case SDLK_a:
							if(event.key.state==SDL_PRESSED)
								if(chosen>0)
									chosen--;	
							break;
						case SDLK_d:
							if(event.key.state==SDL_PRESSED)
								if(chosen < (map_infos.size()-1 ) )
									chosen++;
							break;
						case SDLK_q:
							if(event.key.state==SDL_PRESSED)
								exit(1);
							break;
						case SDLK_RETURN:
							if(event.key.state==SDL_PRESSED)

								game = new Moonlander;
								strncpy(ourprostring, map_infos[chosen]->name_str.c_str(), 5000);
								game->gameinit(ourprostring, screen);
								game->mainloop();
								delete game;						
								SDL_EnableKeyRepeat(1,300);

							break;
							

					}
					break;	

			}

	
 		}

		frame();

		SDL_Flip(screen);

		timezor = frame_timer.timess();	

		if( timezor < FRAME_TIME)
			SDL_Delay(FRAME_TIME-timezor);
	}	
	delete ourprostring;
}
